package orthoplanner.com.google.code.ui;

import java.awt.Point;
import imageadjuster.ImageAdjuster;

import java.io.File;
import java.util.ArrayList;

import orthoplanner.com.google.code.tools.AngleTool;
import orthoplanner.com.google.code.tools.Circle;
import orthoplanner.com.google.code.tools.Drawable;
import orthoplanner.com.google.code.tools.Line;
import orthoplanner.com.google.code.utils.TriangleCheck;

import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PImage;
import processing.core.PVector;

public strictfp class ImageViewer extends PApplet {
	private static final long serialVersionUID = -8213344097654949173L;
	private ImageAdjuster imgAdjuster;
	PFont font;

	public static enum DRAW_MODE {LINE, CIRCLE};
	private float contrast=1.0F;
	public DRAW_MODE DM = null;
	private float imgScale = 1.0F, imgRotation = 0.0F;
	private float tx = 0, ty = 0;
	private ArrayList<Drawable> drawables;
	
	
	
	
	public ArrayList<Drawable> getDrawables() {
		return drawables;
	}

	public void setDrawables(ArrayList<Drawable> drawables) {
		this.drawables = drawables;
	}
	private ArrayList<AngleTool> angles;
	public static boolean FREEZE_IMAGE = true;
	PImage img = null;
	public ImageViewer(int w, int h) {
	}

	@Override
	public void setup() {
		frameRate(20);
		background(0);
		smooth();
		drawables=new ArrayList<Drawable>();
		angles = new ArrayList<AngleTool>();
		font = loadFont("Test.vlw");
		textFont(font);
		textSize(20);
		imgAdjuster=new ImageAdjuster(this);
	}

	@Override
	public void draw() {
		background(255);
		if (img != null) {
			pushMatrix();
			translate(width / 2 + tx, height / 2 + ty);
			rotate(imgRotation);
			scale(imgScale);
			image(img, -(img.width/2), -(img.height/2), img.width, img.height);
			imgAdjuster.contrast(img,contrast);
			popMatrix();
		}
		drawThemUp();
		if (DM == DRAW_MODE.LINE || DM == DRAW_MODE.CIRCLE) {
			cursor(CROSS);
		} else {
			cursor(ARROW);
		}
		drawAngle();
	}

	public void addLine() {
		drawables.add(new Line(new Point(width / 2 + drawables.size() * 20,
				height / 2 - 100), new Point(width / 2 + drawables.size() * 20,
				height / 2 + 100)));
	}

	public void setImageScale(float f) {
		imgScale=(float) map(f,1,1000,0.0,2.0);
		}

	public void setImageRotation(float f) {
		imgRotation = map(f, 1, 1000, -PI, PI);
	}

	@Override
	public void mouseDragged() {
		Point p = new Point(mouseX, mouseY);
		if (DM == DRAW_MODE.LINE || DM == DRAW_MODE.CIRCLE) {
			drawables.get(drawables.size() - 1).setEnd(p);
			} 
		else if (!LineControlPanel.isFreezed()) {
			clearAngles();
			for(int i = drawables.size() - 1; i >= 0; i--) {
				Drawable d=drawables.get(i);
				if(d.isConfigurable(p)){
					d.configure(p);
					break;
				}else if(d.isMovable(p)){
					d.move(mouseX-pmouseX,mouseY-pmouseY);
					break;
				}
			}
			
			if (!FREEZE_IMAGE) {
				tx += mouseX - pmouseX;
				ty += mouseY - pmouseY;
			}
		}
	}

	public void uploadImage(File f) {
		img = loadImage(f.getAbsolutePath());
	}

private void drawThemUp(){
	for(Drawable d:drawables) d.draw(this);
	}
	@Override
	public void mouseClicked() {

		Point p = new Point(mouseX, mouseY);
		
		 if (LineControlPanel.isFreezed() && drawables.size() > 1) {
			double d1 = 200, d2 = 200;
			Line l1 = null, l2 = null;
			for (Drawable  dr : drawables) {
				if(dr instanceof Line){
					Line line=(Line)dr;
					double d = line.distance(p);
					if (d < d1) {
						d2 = d1;
						l2 = l1;
						d1 = d;
						l1 = line;
					} else if (d < d2) {
						d2 = d;
						l2 = line;
					}
		
				}
			}
			if (l1 != null && l2 != null) {
				Point intersect = l1.getIntersect(l2);
				Point first = null, cFirst = null, second = null, cSecond = null;
				if (TriangleCheck.check(l1.getStart(), l2.getStart(),
						intersect, p)) {
					first = l1.getStart();
					cFirst = l1.getEnd();
					second = l2.getStart();
					cSecond = l2.getEnd();
				} else if (TriangleCheck.check(l1.getStart(), l2.getEnd(),
						intersect, p)) {
					first = l1.getStart();
					second = l2.getEnd();
					cFirst = l1.getEnd();
					cSecond = l2.getStart();
				} else if (TriangleCheck.check(l1.getEnd(), l2.getStart(),
						intersect, p)) {
					first = l1.getEnd();
					second = l2.getStart();
					cFirst = l1.getStart();
					cSecond = l2.getEnd();
				} else {
					first = l1.getEnd();
					second = l2.getEnd();
					cFirst = l1.getStart();
					cSecond = l2.getStart();
				}
				Point[] anglePoints = new Point[] { first, intersect, second };
				Point[] cAnglePoints = new Point[] { cFirst, intersect, cSecond };
				Point label = new Point(mouseX, mouseY);
				AngleTool at = new AngleTool(anglePoints, cAnglePoints, label);
				if (!angles.contains(at))
					angles.add(at);
			}
		}

	}

	@Override
	public void mousePressed() {

		if (DM == DRAW_MODE.LINE) {
			drawables.add(new Line(new Point(mouseX, mouseY), new Point(mouseX,
					mouseY)));

		} else if (DM == DRAW_MODE.CIRCLE) {
			drawables.add(new Circle(mouseX, mouseY));
		}
	}

	@Override
	public void mouseReleased() {
		if (DM != null) {
			DM = null;
		}
	}

	private void drawAngle() {
		if (angles.size() != 0) {

			for (AngleTool at : angles) {
				fill(20, 0, 233, 60);
				Point[] anglePoints = at.getAnglePoints();
				Point[] cAnglePoints = at.getcAnglePoints();
				PVector v1 = new Line(anglePoints[1], anglePoints[0])
						.toVector().normalize(null);
				v1.mult(50);
				Point center = anglePoints[1];
				PVector v2 = new Line(anglePoints[1], anglePoints[2])
						.toVector().normalize(null);
				v2.mult(50);
				triangle(v1.x + center.x, v1.y + center.y, center.x, center.y,
						v2.x + center.x, v2.y + center.y);
				line(anglePoints[0].x, anglePoints[0].y, anglePoints[1].x,
						anglePoints[1].y);
				line(anglePoints[1].x, anglePoints[1].y, anglePoints[2].x,
						anglePoints[2].y);

				double angle = (180.0 / Math.PI)
						* new Line(anglePoints[1], anglePoints[0])
								.getAngle(new Line(anglePoints[1],
										anglePoints[2]));
				double angleO = (180.0 / Math.PI)
						* new Line(cAnglePoints[1], cAnglePoints[0])
								.getAngle(new Line(cAnglePoints[1],
										cAnglePoints[2]));
				fill(255, 0, 0, 255);
				angle = (angle + angleO) / 2.0;
				text(" " + Math.round(angle) + " ", at.getLabel().x, at
						.getLabel().y);
			}
		}

	}

	public void clearAngles() {
		noLoop();
		angles.clear();
		loop();
		
	}
	public void clearDrawables(){
			drawables.clear();
	}

	public void setImageContrast(int value) {
	contrast=value/100.0F;	
	}

}
